#include "sz_request.h"
#include "curl_http/curl_http.h"
#include "common.h"
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#define GET_STRING(_v) _v.IsString() ? _v.GetString() : ""
#define GET_INT(_v) _v.IsInt() ? _v.GetInt() : 0
#define GET_FLOAT(_v) _v.IsFloat() ? _v.GetFloat() : 0.0
namespace sz
{
//生成0-1间的随机数。
void get_rand(double& p)
{
    srand(time(NULL));
    p = rand() % (NUM + 1) / (double)(NUM + 1);
}
curl_http g_http_request;
// GET /api/report/ShowReport/data?SHOWTYPE=JSON&CATALOGID=1110&TABKEY=tab1&PAGENO=1&random=0.0000011815016130 HTTP/1.1
// Host: www.szse.cn
// Connection: keep-alive
// Cache-Control: max-age=0
// Upgrade-Insecure-Requests: 1
// User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36
// Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
// Accept-Encoding: gzip, deflate
// Accept-Language: zh-CN,zh;q=0.9
bool get_stock_lists(int pag_num, int& pag_count, std::vector<std::string>& codes)
{
    double rp = 0;
    get_rand(rp);
    char s[256] = { 0 };
    sprintf(s,"http://www.szse.cn/api/report/ShowReport/data?SHOWTYPE=JSON&CATALOGID=1110&TABKEY=tab1&PAGENO=%d&random=%.16f",
        pag_num, rp);

    http_header head;
    head.accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9";

    std::string req = s;
    auto t = bm::time::get_current_timestamp();
    std::string result = g_http_request.get(req, head);
    auto t2 = bm::time::get_current_timestamp();
    std::cout << "request pag_num=" << pag_num << " use time:" << t2 - t << " ms" << std::endl;
    // Json::Value v;
    // bm::file::write_file("stock_lists.txt", result);
    rapidjson::Document doc;
    doc.Parse(result.c_str());
    if(!doc.IsArray())
        return false;
    
    // for(auto i : v)
    for(rapidjson::SizeType j = 0; j < doc.Size(); j++)
    {
        rapidjson::Value& d = doc[j]["data"];
        if(d.IsNull())
            continue;

        rapidjson::Value& mate_data     = doc[j]["metadata"];
        int pagesize                    = mate_data["pagesize"].GetInt();    // 当前页的数量
        int pageno                      = mate_data["pageno"].GetInt();      // 当前页号
        int pagecount                   = mate_data["pagecount"].GetInt();   // 总页数
        
        pag_count = pagecount > 0 ? pagecount : pag_count;
        rapidjson::Value& conditions    = mate_data["conditions"];           // 条件查询的数据 其中第二项是行业

        // for(auto j : conditions)
        if(!conditions.IsArray())
            continue;

        for(rapidjson::SizeType k = 0; k < conditions.Size(); k++)
        {
            std::string lab = conditions[k]["label"].GetString();
            rapidjson::Value& ops = conditions[k]["options"];
            if(!ops.IsArray())
                continue;
            for(rapidjson::SizeType m = 0; m < ops.Size(); m++)
            {
                std::string text  = ops[m]["text"].GetString();
                std::string value = ops[m]["value"].GetString();
                // if(!value.empty());
                if(lab == "行业类别")
                {
                    // std::cout << "text:" << text << ",value:" << value << std::endl;
                }
                if(lab == "板块")
                {
                }
            }
        }
        if(!d.IsArray())
            continue;
        for(rapidjson::SizeType n = 0; n < d.Size(); n++)
        {
            std::string bk     = d[n]["bk"].GetString();        // 板块
            std::string agdm   = d[n]["agdm"].GetString();      // A股代码
            std::string agjc   = d[n]["agjc"].GetString();      // A股简称
            std::string agssrq = d[n]["agssrq"].GetString();    // 上市日期
            std::string agzgb  = d[n]["agzgb"].GetString();     // 总股本
            std::string agltgb = d[n]["agltgb"].GetString();    // 流通股本
            std::string sshymc = d[n]["sshymc"].GetString();    // 所属行业

            if(bk == "中小板") bk = "中小企业板";
            codes.push_back(agdm);
        }
    }
    auto t3 = bm::time::get_current_timestamp();
    std::cout << "page parse json use time:" << t3 - t2 << " ms" << std::endl;
    return true;
}
void get_stock_time_data(const std::string& code, std::vector<std::string>& sqls)
{
    std::string dir = "sqls";
    if(!fs::exists(dir))
        fs::create_directories(dir);

    std::string sqlfile = dir + "/all.sql";
    
    double rp = 0;
    get_rand(rp);
    char s[256] = { 0 };
    sprintf(s, "http://www.szse.cn/api/market/ssjjhq/getTimeData?random=%0.16f&marketId=1&code=%s", rp, code.c_str());
    std::string rep = s;
    http_header head;

    auto t = bm::time::get_current_timestamp();
    std::string req = g_http_request.get(rep, head);
    auto t2 = bm::time::get_current_timestamp();
    // std::cout << "request " << code << " use time:" << t2 - t << " ms" << std::endl;
    // bm::file::write_file("code.txt", req);

    rapidjson::Document d;
    d.Parse(req.c_str());
    // rapidjson::Value& j_data = d["data"];
    if(d.IsObject() && !d.IsNull())
    {
        rapidjson::Value& j_data    = d["data"];
        if(j_data.IsNull())
        {
            bm::file::write_file("code.txt", req);
            return;
        }
        std::string code            = GET_STRING(j_data["code"]);           // 股票代码
        std::string name            = GET_STRING(j_data["name"]);           // 股票名字
        std::string close           = GET_STRING(j_data["close"]);          // 昨收价
        std::string open            = GET_STRING(j_data["open"]);           // 开盘价
        std::string now             = GET_STRING(j_data["now"]);            // 最新价
        std::string high            = GET_STRING(j_data["high"]);           // 最高点
        std::string low             = GET_STRING(j_data["low"]);            // 最低点
        int volume                  = GET_INT(j_data["volume"]);            // 成交量(手)
        float amount                = GET_FLOAT(j_data["amount"]);          // 成就额(元)
        std::string delta           = GET_STRING(j_data["delta"]);          // 涨跌价
        std::string delta_precent   = GET_STRING(j_data["deltaPercent"]);   // 涨跌幅(%)
        std::string market_time     = GET_STRING(j_data["marketTime"]);     // 时间
        std::string::size_type pos  = market_time.find(" ");
        std::string dt,ti;
        if(pos != std::string::npos)
        {
            dt = market_time.substr(0, pos);
            ti = market_time.substr(pos + 1);
        }
        else dt = market_time;
        if(code.empty() || name.empty() || close.empty() || open.empty() || now.empty() ||
        high.empty() || low.empty() || delta.empty() || delta_precent.empty() || market_time.empty())
            return;
        rapidjson::Value& picupdata = j_data["picupdata"];                  // 分钟数据
        std::string day_sql;
        char sql[512] = { 0 };
        sprintf(sql, "insert into t_day_data (`id`,`code`,`name`,`close`,`open`,`now`,"
        "`high`,`low`,`volume`,`amount`,`delta`,`delta_percent`,`market_time`,`date`) "
        "values(NULL,'%s','%s',%s,%s,%s,%s,%s,%d,%0.2f,%s,%s,'%s','%s');\n",code.c_str(),name.c_str(),close.c_str(),
        open.c_str(), now.c_str(), high.c_str(), low.c_str(), volume, amount,
        delta.c_str(), delta_precent.c_str(), market_time.c_str(), dt.c_str());
        day_sql = sql;
        bm::file::write_file(sqlfile, sql);
        // bm::file::write_file(sqlfile, sql);
        sqls.push_back(sql);
        // std::vector<std::string> sqls;
        if(picupdata.IsArray())
        {
            std::string before = "insert into t_minute_data (`day_id`,`time`,`now`,`avarge_price`,`delta`,`delta_percent`,`volume`,`amount`) values ";
            std::string values;
            for(rapidjson::SizeType j = 0; j < picupdata.Size(); j++)
            {
                rapidjson::Value& i = picupdata[j];
                auto t  = i[0].GetString();      // 时间
                auto cp = i[1].GetString();      // 最新价
                auto ap = i[2].GetString();      // 平均价
                auto d  = i[3].GetString();      // 涨跌价
                auto dp = i[4].GetString();      // 涨跌幅(%)
                auto v  = i[5].GetInt();         // 成交量(手)
                auto a  = i[6].GetFloat();       // 成交额(元)

                char picsql[256] = { 0 };
                sprintf(picsql, "((select id from t_day_data where `code`='%s' and `date`='%s'),'%s',%s,%s,%s,%s,%d,%0.2f),",
                code.c_str(),dt.c_str(), t, cp, ap, d, dp, v, a);

                values += picsql;
                // sqls.push_back(picsql);
                // bm::file::write_file(sqlfile, picsql);
            }
            if(!values.empty())
            {
                values.pop_back();
                sqls.push_back(before + values);
            }
        }
    }
}
}